{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Teleport\n",
    "\n",
    "![]()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Quantum teleportation provides a way of moving a quantum state from one\n",
    "location  to another without having to move physical particle(s) along\n",
    "with it. This is done with the help of previously shared quantum\n",
    "entanglement between the sending and the receiving locations and\n",
    "classical communication.\n",
    " \n",
    "To see how to implement this in Q#, we first define a `Teleport` Q# operation that transfers the state of one qubit\n",
    "into another:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/json": "[\"Teleport\"]",
      "text/html": [
       "<ul><li>Teleport</li></ul>"
      ],
      "text/plain": [
       "Teleport"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "/// # Summary\n",
    "/// Sends the state of one qubit to a target qubit by using\n",
    "/// teleportation.\n",
    "/// \n",
    "/// Notice that after calling Teleport, the state of `msg` is\n",
    "/// collapsed.\n",
    "///\n",
    "/// # Input\n",
    "/// ## msg\n",
    "/// A qubit whose state we wish to send.\n",
    "/// ## target\n",
    "/// A qubit initially in the |0〉 state that we want to send\n",
    "/// the state of msg to.\n",
    "operation Teleport (msg : Qubit, target : Qubit) : Unit {\n",
    "\n",
    "    using (register = Qubit()) {\n",
    "        // Create some entanglement that we can use to send the message.\n",
    "        H(register);\n",
    "        CNOT(register, target);\n",
    "\n",
    "        // Encode the message into the entangled pair,\n",
    "        // and measure the qubits to extract the classical data\n",
    "        // we need to correctly decode the message into the target qubit:\n",
    "        CNOT(msg, register);\n",
    "        H(msg);\n",
    "        let data1 = M(msg);\n",
    "        let data2 = M(register);\n",
    "\n",
    "        // decode the message by applying the corrections on\n",
    "        // the target qubit accordingly:\n",
    "        if (data1 == One) { Z(target); }\n",
    "        if (data2 == One) { X(target); }\n",
    "\n",
    "        // Reset our \"register\" qubit before releasing it.\n",
    "        Reset(register);\n",
    "    }\n",
    "}\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that the state of the original qubit is destroyed when we perform a measurement on it, so the `Teleport` Q# operation does not violate the [non-cloning theorem](https://docs.microsoft.com/quantum/concepts/pauli-measurements#the-no-cloning-theorem).\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can then show how to move a random quantum state\n",
    "(for this sample, either |+> or |->) using `Teleport`without loosing any state information:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/json": "[\"TeleportRandomMessage\"]",
      "text/html": [
       "<ul><li>TeleportRandomMessage</li></ul>"
      ],
      "text/plain": [
       "TeleportRandomMessage"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "open Microsoft.Quantum.Samples.Teleportation;\n",
    "\n",
    "/// # Summary\n",
    "/// Uses teleportation to send a randomly picked |-> or |+> state\n",
    "/// to another.\n",
    "operation TeleportRandomMessage () : Unit {\n",
    "\n",
    "    using (qubits = Qubit[2]) {\n",
    "\n",
    "        // Ask for some qubits that we can use to teleport.\n",
    "        let msg = qubits[0];\n",
    "        let target = qubits[1];\n",
    "\n",
    "        PrepareRandomMessage(msg);\n",
    "\n",
    "        // Use the operation we defined above.\n",
    "        Teleport(msg, target);\n",
    "\n",
    "        // Report message received:\n",
    "        if (IsPlus(target))  { Message(\"Received |+>\"); }\n",
    "        if (IsMinus(target)) { Message(\"Received |->\"); }\n",
    "\n",
    "        // Reset all of the qubits that we used before releasing\n",
    "        // them.\n",
    "        ResetAll(qubits);\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Notice `TeleportRandomMessage` uses some operations defined in the Notebooks workspace. To get the  complete list of workspace operations use the `%workspace` command:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/json": "[\"Microsoft.Quantum.Samples.Teleportation.IsMinus\",\"Microsoft.Quantum.Samples.Teleportation.IsPlus\",\"Microsoft.Quantum.Samples.Teleportation.PrepareRandomMessage\",\"Microsoft.Quantum.Samples.Teleportation.SetToMinus\",\"Microsoft.Quantum.Samples.Teleportation.SetToPlus\",\"Microsoft.Quantum.Samples.Teleportation.Teleport\",\"Microsoft.Quantum.Samples.Teleportation.TeleportClassicalMessage\",\"Microsoft.Quantum.Samples.Teleportation.TeleportRandomMessage\"]",
      "text/html": [
       "<ul><li>Microsoft.Quantum.Samples.Teleportation.IsMinus</li><li>Microsoft.Quantum.Samples.Teleportation.IsPlus</li><li>Microsoft.Quantum.Samples.Teleportation.PrepareRandomMessage</li><li>Microsoft.Quantum.Samples.Teleportation.SetToMinus</li><li>Microsoft.Quantum.Samples.Teleportation.SetToPlus</li><li>Microsoft.Quantum.Samples.Teleportation.Teleport</li><li>Microsoft.Quantum.Samples.Teleportation.TeleportClassicalMessage</li><li>Microsoft.Quantum.Samples.Teleportation.TeleportRandomMessage</li></ul>"
      ],
      "text/plain": [
       "Microsoft.Quantum.Samples.Teleportation.IsMinus, Microsoft.Quantum.Samples.Teleportation.IsPlus, Microsoft.Quantum.Samples.Teleportation.PrepareRandomMessage, Microsoft.Quantum.Samples.Teleportation.SetToMinus, Microsoft.Quantum.Samples.Teleportation.SetToPlus, Microsoft.Quantum.Samples.Teleportation.Teleport, Microsoft.Quantum.Samples.Teleportation.TeleportClassicalMessage, Microsoft.Quantum.Samples.Teleportation.TeleportRandomMessage"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%workspace"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can get the documentation of each operation by using the `?` magic:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/json": "{\"name\":\"Microsoft.Quantum.Samples.Teleportation.PrepareRandomMessage\",\"kind\":1,\"source\":\"C:/Repos/Solid/Samples/Samples/src/Teleportation/Utils.qs\",\"documentation\":\" # Summary\\n Randomly prepares the qubit into |+> or |->\"}",
      "text/html": [
       "<h4><i class=\"fa fas fa-terminal\"></i> Microsoft.Quantum.Samples.Teleportation.PrepareRandomMessage <a href=\"C:/Repos/Solid/Samples/Samples/src/Teleportation/Utils.qs\"><i class=\"fa fas fa-code\"></i></a></h4><h1>Summary</h1>\n",
       "<p>Randomly prepares the qubit into |+&gt; or |-&gt;</p>\n"
      ],
      "text/plain": [
       "Microsoft.Quantum.Samples.Teleportation.PrepareRandomMessage"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Microsoft.Quantum.Samples.Teleportation.PrepareRandomMessage?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Finally, use `%simulate` to run the `TeleportRandomMessage` operation using the `QuantumSimulator`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sending |+>\n",
      "Received |+>\n"
     ]
    },
    {
     "data": {
      "application/json": "{\"@type\":\"tuple\"}",
      "text/plain": [
       "()"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%simulate TeleportRandomMessage"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/json": "{\"rows\":[{\"@type\":\"@tuple\",\"Item1\":\"iqsharp\",\"Item2\":\"0.5.1903.2702\"},{\"@type\":\"@tuple\",\"Item1\":\"Jupyter Core\",\"Item2\":\"1.1.12077.0\"}]}",
      "text/html": [
       "<table><thead><tr><th>Component</th><th>Version</th></tr></thead><tbody><tr><td>iqsharp</td><td>0.5.1903.2702</td></tr><tr><td>Jupyter Core</td><td>1.1.12077.0</td></tr></tbody></table>"
      ],
      "text/plain": [
       "Component    Version\r\n",
       "------------ -------------\r\n",
       "iqsharp      0.5.1903.2702\r\n",
       "Jupyter Core 1.1.12077.0\r\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%version"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Q#",
   "language": "qsharp",
   "name": "iqsharp"
  },
  "language_info": {
   "file_extension": ".qs",
   "mimetype": "text/x-qsharp",
   "name": "qsharp",
   "version": "0.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
